#pragma once
#include <Singleton.h>
#include <hiredis/hiredis.h>
#include <queue>
#include <atomic>
#include <condition_variable>

class RedisConPool
{
public:
    RedisConPool(size_t pool_size, const char* host, int port, const char* password);

    ~RedisConPool();

    redisContext* GetConnection();

    void ReturnConnection(redisContext* context);

    void Close();

private:
    const char* _host;
    int _port;
    size_t _pool_size;
    std::atomic<bool> _b_stop;
    std::queue<redisContext*> _connections;
    std::mutex _mutex;
    std::condition_variable _cond;
};


class RedisMng : public Singleton<RedisMng>, public std::enable_shared_from_this<RedisMng>
{
    friend class Singleton<RedisMng>;

private:
    RedisMng();

public:
    ~RedisMng();
    RedisMng(const RedisMng&) = delete;
    RedisMng& operator=(const RedisMng&) = delete;

    //获取key对应的value
    bool GetByKey(const std::string& key, std::string& value);
    //设置key和value
    bool Set(const std::string& key, const std::string& value);
    //密码认证
    bool Auth(const std::string& password);
    //左侧push
    bool LPush(const std::string& key, const std::string& value);
    //左侧pop
    bool LPop(const std::string& key, std::string& value);
    //右侧push
    bool RPush(const std::string& key, const std::string& value);
    //右侧pop
    bool RPop(const std::string& key, std::string& value);
    //HSet操作
    bool HSet(const std::string& key, const std::string& hkey, const std::string& value);
    bool HSet(const char* key, const char* hkey, const char* hvalue, size_t hvaluelen);
    //HGet操作
    std::string HGet(const std::string& key, const std::string& hkey);
    //删除key
    bool Del(const std::string& key);
    //判断键值是否存在
    bool ExistsKey(const std::string& key);
    //关闭
    void Close() const;

private:
    redisReply* _reply;
    std::unique_ptr<RedisConPool> _con_pool;
};
